import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:xbaistack/common/gen.dart';

import 'package:xbaistack/model/model.dart';
import 'package:xbaistack/model/pager.dart';
import 'package:xbaistack/utils/helper.dart';
import 'package:xbaistack/widget/data_loader.dart';

/// 刷新列表中用于构造列表的每一项的构造器
/// * @param [M] 列表数据的泛型类型
/// * @return [Widget] 列表构造器返回的渲染视图
typedef ItemBuilder<M extends Model<M>> =
    Widget Function(BuildContext context, int index, List<M> datas, M model);

/// 刷新列表中用于提供异步任务的构造器，负责返回一个最终的异步任务 [Future]。
/// * @param [M] 列表数据的泛型类型
/// * @return [Future] 用于最后执行的异步任务
typedef RequestFuture<M extends Model<M>> = Future<Pager<M>> Function(int page);

/// 刷新组件控制器，用处有二：
///
/// 1. 提供 [RequestFuture] 的参数设置；
/// 2. 提供外部手动刷新的调用方法 [refresh]；
///
/// * @author xbaistack
/// * @since 2025/04/01
class RefreshController<M extends Model<M>>
    extends BaseController<RefreshListState<M, RefreshList<M>>> {
  final RequestFuture<M> future;

  RefreshController({required this.future});

  void refresh() => state?.refresh();
}

/// 数据刷新列表（或者数据分页列表），用于提供数据分页操作的组件，组件内包含以下几个功能点：
///
/// 1. 自动检测网络状态，在首次运行检测无网络的情况下，展示无网络提示，并提供重试操作；
/// 2. 提供在执行异步任务过程中的状态视图展示；
/// 3. 提供下拉列表刷新功能；
/// 4. 提供上拉加载更多（翻页）功能；
///
/// * @author xbaistack
/// * @since 2025/04/01
class RefreshList<M extends Model<M>> extends StatefulWidget {
  final RefreshController<M> controller;
  final ItemBuilder<M> builder;

  RefreshList({required this.controller, required this.builder})
    : super(key: controller.key);

  @override
  State<StatefulWidget> createState() => RefreshListState<M, RefreshList<M>>();
}

class RefreshListState<M extends Model<M>, W extends RefreshList<M>>
    extends State<W> {
  late final EasyRefreshController _controller;

  Pager<M>? _pager;
  List<M>? _items;

  Pager<M>? get pager => _pager;
  List<M>? get items => _items;

  bool get isNoMore => _pager == null || _pager!.page >= _pager!.totalPage;

  @override
  void initState() {
    super.initState();
    _controller = EasyRefreshController(
      controlFinishRefresh: true,
      controlFinishLoad: true,
    );
  }

  @override
  void dispose() {
    super.dispose();
    _pager = null;
    _items = null;
    _controller.dispose();
  }

  void refresh() => _controller.callRefresh();

  @override
  Widget build(BuildContext context) {
    // 下拉刷新 & 上拉加载更多会走这里。
    if (_pager != null) {
      return _refreshWidget(context);
    }
    // 仅首次加载时需要显示加载动画以及网络状态监听，后续则不需要。
    return DataLoader(
      future: () => widget.controller.future(1),
      builder: (pager) {
        _pager = pager;
        _items = pager.items;
        return _refreshWidget(context);
      },
    );
  }

  Widget widgetOf(
    BuildContext context,
    int count,
    List<M> datas,
    double cacheExtent,
  ) {
    return ListView.builder(
      itemCount: count,
      cacheExtent: cacheExtent,
      addRepaintBoundaries: false,
      itemBuilder: (context, index) {
        return widget.builder.call(context, index, datas, _items![index]);
      },
    );
  }

  Widget _refreshWidget(BuildContext context) {
    final iconTheme = context.theme.data.iconTheme.copyWith(
      color: context.theme.themeColor,
    );
    return EasyRefresh(
      refreshOnStart: false,
      resetAfterRefresh: true,
      controller: _controller,
      onRefresh: _onRefresh,
      onLoad: _onLoadMore,
      header: ClassicHeader(
        spacing: 5,
        showText: true,
        triggerOffset: kToolbarHeight,
        showMessage: false,
        dragText: '下拉以刷新',
        armedText: '释放开始刷新',
        readyText: '刷新中',
        processingText: '刷新中',
        processedText: '刷新成功',
        noMoreText: '没有更多数据',
        failedText: '加载失败',
        iconTheme: iconTheme,
        progressIndicatorSize: 14,
        textStyle: TextStyle(fontSize: 12, color: context.theme.themeColor),
      ),
      footer: ClassicFooter(
        spacing: 5,
        showText: isNoMore,
        showMessage: false,
        noMoreText: '-- 我是有底线的，没有更多了 --',
        iconTheme: isNoMore
            ? iconTheme.copyWith(color: Colors.transparent)
            : iconTheme,
        iconDimension: isNoMore ? 0 : 24,
        progressIndicatorSize: 14,
        triggerOffset: 40,
        textStyle: const TextStyle(fontSize: 12, color: Colors.black38),
      ),
      child: widgetOf(
        context,
        _items?.length ?? 0,
        _items ?? [],
        (_pager?.pageSize ?? 5).toDouble(),
      ),
    );
  }

  void _onRefresh() {
    widget.controller
        .future(1)
        .then((pager) {
          setState(() {
            _pager = pager;
            _items = pager.items;
            _controller.finishRefresh();
            _controller.resetFooter();
          });
        })
        .catchError((error) {
          setState(() {
            _controller.finishRefresh(IndicatorResult.fail);
          });
        });
  }

  void _onLoadMore() {
    widget.controller
        .future((_pager?.page ?? 1) + 1)
        .then((pager) {
          setState(() {
            _pager = pager;
            if (Helper.isNotEmpty(pager.items)) {
              _items!.addAll(pager.items!);
            }
            _controller.finishLoad(
              isNoMore ? IndicatorResult.noMore : IndicatorResult.success,
            );
          });
        })
        .catchError((error) {
          setState(() {
            _controller.finishLoad(IndicatorResult.fail);
          });
        });
  }
}
